﻿package Framework.Serialize
{
    import Framework.Util.*;
    import flash.utils.*;

    public class SerializeStream extends Object
    {
        private var _byteArray:ByteArray;
        private var _seqDataStack:SeqData = null;

        public function SerializeStream()
        {
            this.byteArray = new ByteArray();
            return;
        }// end function

        public function readByte() : int
        {
            var _loc_1:* = this._byteArray.readByte();
            if (_loc_1 < 0)
            {
                return _loc_1 + 256;
            }
            return _loc_1;
        }// end function

        public function readByteSeq() : Array
        {
            var _loc_1:* = new Array();
            var _loc_2:* = this.readSize();
            var _loc_3:int = 0;
            while (_loc_3 < _loc_2)
            {
                
                _loc_1.push(this.readByte());
                _loc_3++;
            }
            return _loc_1;
        }// end function

        public function writeByte(param1:int) : void
        {
            this._byteArray.writeByte(param1);
            return;
        }// end function

        public function writeByteSeq(param1:Array) : void
        {
            if (param1 == null)
            {
                this.writeSize(0);
                return;
            }
            this.writeSize(param1.length);
            var _loc_2:int = 0;
            while (_loc_2 < param1.length)
            {
                
                this.writeByte(param1[_loc_2]);
                _loc_2++;
            }
            return;
        }// end function

        public function writeBool(param1:Boolean) : void
        {
            if (param1)
            {
                this._byteArray.writeByte(1);
            }
            else
            {
                this._byteArray.writeByte(0);
            }
            return;
        }// end function

        public function writeBoolSeq(param1:Array) : void
        {
            if (param1 == null)
            {
                this.writeSize(0);
                return;
            }
            this.writeSize(param1.length);
            var _loc_2:int = 0;
            while (_loc_2 < param1.length)
            {
                
                this.writeBool(param1[_loc_2]);
                _loc_2++;
            }
            return;
        }// end function

        public function readBool() : Boolean
        {
            var _loc_1:* = this._byteArray.readByte();
            return !_loc_1 == 0;
        }// end function

        public function readBoolSeq() : Array
        {
            var _loc_1:* = new Array();
            var _loc_2:* = this.readSize();
            var _loc_3:int = 0;
            while (_loc_3 < _loc_2)
            {
                
                _loc_1.push(this.readBool());
                _loc_3++;
            }
            return _loc_1;
        }// end function

        public function readSize() : int
        {
            var _loc_1:* = this._byteArray.readUnsignedByte();
            if (_loc_1 == 255)
            {
                return this._byteArray.readInt();
            }
            return _loc_1;
        }// end function

        public function writeSize(param1:int) : void
        {
            if (param1 < 255)
            {
                this._byteArray.writeByte(param1);
            }
            else
            {
                this._byteArray.writeByte(255);
                this._byteArray.writeInt(param1);
            }
            return;
        }// end function

        public function readInt() : int
        {
            return this._byteArray.readInt();
        }// end function

        public function readIntSeq() : Array
        {
            var _loc_1:* = new Array();
            var _loc_2:* = this.readSize();
            var _loc_3:int = 0;
            while (_loc_3 < _loc_2)
            {
                
                _loc_1.push(this.readInt());
                _loc_3++;
            }
            return _loc_1;
        }// end function

        public function writeInt(param1:int) : void
        {
            this._byteArray.writeInt(param1);
            return;
        }// end function

        public function writeIntSeq(param1:Array) : void
        {
            if (param1 == null)
            {
                this.writeSize(0);
                return;
            }
            this.writeSize(param1.length);
            var _loc_2:int = 0;
            while (_loc_2 < param1.length)
            {
                
                this.writeInt(param1[_loc_2]);
                _loc_2++;
            }
            return;
        }// end function

        public function readShort() : int
        {
            return this._byteArray.readShort();
        }// end function

        public function readShortSeq() : Array
        {
            var _loc_1:* = new Array();
            var _loc_2:* = this.readSize();
            var _loc_3:int = 0;
            while (_loc_3 < _loc_2)
            {
                
                _loc_1.push(this.readShort());
                _loc_3++;
            }
            return _loc_1;
        }// end function

        public function writeShort(param1:int) : void
        {
            this._byteArray.writeShort(param1);
            return;
        }// end function

        public function writeShortSeq(param1:Array) : void
        {
            if (param1 == null)
            {
                this.writeSize(0);
                return;
            }
            this.writeSize(param1.length);
            var _loc_2:int = 0;
            while (_loc_2 < param1.length)
            {
                
                this.writeShort(param1[_loc_2]);
                _loc_2++;
            }
            return;
        }// end function

        public function readLong() : Number
        {
            var _loc_1:* = this._byteArray.readInt();
            var _loc_2:* = this._byteArray.readInt();
            return _loc_2 * (uint.MAX_VALUE + 1) + _loc_1;
        }// end function

        public function readLongSeq() : Array
        {
            var _loc_1:* = new Array();
            var _loc_2:* = this.readSize();
            var _loc_3:int = 0;
            while (_loc_3 < _loc_2)
            {
                
                _loc_1.push(this.readLong());
                _loc_3++;
            }
            return _loc_1;
        }// end function

        public function writeLong(param1:Number) : void
        {
            var _loc_2:* = param1 % (uint.MAX_VALUE + 1);
            var _loc_3:* = param1 / (uint.MAX_VALUE + 1);
            if (param1 >= 0)
            {
                this._byteArray.writeUnsignedInt(_loc_2);
                this._byteArray.writeInt(_loc_3);
            }
            else if (_loc_3 == 0)
            {
                this._byteArray.writeUnsignedInt(param1);
                this._byteArray.writeInt(-1);
            }
            else
            {
                this._byteArray.writeUnsignedInt(_loc_2);
                this._byteArray.writeInt(_loc_3);
            }
            return;
        }// end function

        public function writeLongSeq(param1:Array) : void
        {
            if (param1 == null)
            {
                this.writeSize(0);
                return;
            }
            this.writeSize(param1.length);
            var _loc_2:int = 0;
            while (_loc_2 < param1.length)
            {
                
                this.writeLong(param1[_loc_2]);
                _loc_2++;
            }
            return;
        }// end function

        public function readString() : String
        {
            var _loc_1:* = this.readSize();
            return this._byteArray.readUTFBytes(_loc_1);
        }// end function

        public function readStringSeq() : Array
        {
            var _loc_1:* = new Array();
            var _loc_2:* = this.readSize();
            var _loc_3:int = 0;
            while (_loc_3 < _loc_2)
            {
                
                _loc_1.push(this.readString());
                _loc_3++;
            }
            return _loc_1;
        }// end function

        public function writeString(param1:String) : void
        {
            if (param1 == null)
            {
                this.writeSize(0);
                return;
            }
            var _loc_2:* = new ByteArray();
            _loc_2.writeUTFBytes(param1);
            this.writeSize(_loc_2.length);
            this._byteArray.writeBytes(_loc_2);
            return;
        }// end function

        public function writeStringSeq(param1:Array) : void
        {
            if (param1 == null)
            {
                this.writeSize(0);
                return;
            }
            this.writeSize(param1.length);
            var _loc_2:int = 0;
            while (_loc_2 < param1.length)
            {
                
                this.writeString(param1[_loc_2]);
                _loc_2++;
            }
            return;
        }// end function

        public function readFloat() : Number
        {
            return this._byteArray.readFloat();
        }// end function

        public function readFloatSeq() : Array
        {
            var _loc_1:* = new Array();
            var _loc_2:* = this.readSize();
            var _loc_3:int = 0;
            while (_loc_3 < _loc_2)
            {
                
                _loc_1.push(this.readFloat());
                _loc_3++;
            }
            return _loc_1;
        }// end function

        public function writeFloat(param1:Number) : void
        {
            this._byteArray.writeFloat(param1);
            return;
        }// end function

        public function writeFloatSeq(param1:Array) : void
        {
            if (param1 == null)
            {
                this.writeSize(0);
                return;
            }
            this.writeSize(param1.length);
            var _loc_2:int = 0;
            while (_loc_2 < param1.length)
            {
                
                this.writeFloat(param1[_loc_2]);
                _loc_2++;
            }
            return;
        }// end function

        public function readDouble() : Number
        {
            return this._byteArray.readDouble();
        }// end function

        public function readDoubleSeq() : Array
        {
            var _loc_1:* = new Array();
            var _loc_2:* = this.readSize();
            var _loc_3:int = 0;
            while (_loc_3 < _loc_2)
            {
                
                _loc_1.push(this.readDouble());
                _loc_3++;
            }
            return _loc_1;
        }// end function

        public function writeDouble(param1:Number) : void
        {
            this._byteArray.writeDouble(param1);
            return;
        }// end function

        public function writeDoubleSeq(param1:Array) : void
        {
            if (param1 == null)
            {
                this.writeSize(0);
                return;
            }
            this.writeSize(param1.length);
            var _loc_2:int = 0;
            while (_loc_2 < param1.length)
            {
                
                this.writeDouble(param1[_loc_2]);
                _loc_2++;
            }
            return;
        }// end function

        public function readDate() : Date
        {
            return new Date(this.readInt() * 1000);
        }// end function

        public function readDateSeq() : Array
        {
            var _loc_1:* = new Array();
            var _loc_2:* = this.readSize();
            var _loc_3:int = 0;
            while (_loc_3 < _loc_2)
            {
                
                _loc_1.push(this.readDate());
                _loc_3++;
            }
            return _loc_1;
        }// end function

        public function writeDate(param1:Date) : void
        {
            if (param1 == null)
            {
                this._byteArray.writeInt(0);
                return;
            }
            this._byteArray.writeInt(param1.time / 1000);
            return;
        }// end function

        public function writeDateSeq(param1:Array) : void
        {
            if (param1 == null)
            {
                this.writeSize(0);
                return;
            }
            this.writeSize(param1.length);
            var _loc_2:int = 0;
            while (_loc_2 < param1.length)
            {
                
                this.writeDate(param1[_loc_2]);
                _loc_2++;
            }
            return;
        }// end function

        public function writeByteArray(param1:SerializeStream) : void
        {
            this.byteArray.writeBytes(param1.byteArray);
            return;
        }// end function

        public function writeException(param1:Exception) : void
        {
            this.writeString(param1.message);
            this.writeInt(param1.code);
            return;
        }// end function

        public function readException(param1:Exception) : void
        {
            param1.message = this.readString();
            param1.code = this.readInt();
            return;
        }// end function

        public function startSeq(param1:int, param2:int) : void
        {
            if (param1 == 0)
            {
                return;
            }
            var _loc_3:* = new SeqData(param1, param2);
            _loc_3.previous = this._seqDataStack;
            this._seqDataStack = _loc_3;
            var _loc_4:* = this.getBytesLeft();
            if (this._seqDataStack.previous == null)
            {
                if (param1 * param2 > _loc_4)
                {
                    throw new SerializeException();
                }
            }
            else
            {
                this.checkSeqLen(_loc_4);
            }
            return;
        }// end function

        public function checkSeq() : void
        {
            this.checkSeqLen(this.getBytesLeft());
            return;
        }// end function

        public function checkSeqLen(param1:int) : void
        {
            var _loc_2:int = 0;
            var _loc_3:* = this._seqDataStack;
            do
            {
                
                _loc_2 = _loc_2 + (_loc_3.numElements - 1) * _loc_3.minSize;
                _loc_3 = _loc_3.previous;
            }while (_loc_3 != null)
            if (_loc_2 > param1)
            {
                throw new SerializeException();
            }
            return;
        }// end function

        public function endElement() : void
        {
            var _loc_1:* = this._seqDataStack;
            var _loc_2:* = this._seqDataStack.numElements - 1;
            _loc_1.numElements = _loc_2;
            return;
        }// end function

        public function endSeq(param1:int) : void
        {
            if (param1 == 0)
            {
                return;
            }
            this._seqDataStack = this._seqDataStack.previous;
            return;
        }// end function

        public function checkFixedSeq(param1:int, param2:int) : void
        {
            var _loc_3:* = this.getBytesLeft();
            if (this._seqDataStack == null)
            {
                if (param1 * param2 > _loc_3)
                {
                    throw new SerializeException();
                }
            }
            else
            {
                this.checkSeqLen(_loc_3 - param1 * param2);
            }
            return;
        }// end function

        public function getBytesLeft() : int
        {
            return this.byteArray.length - this.byteArray.position;
        }// end function

        public function clear() : void
        {
            if (this._byteArray)
            {
                this._byteArray.clear();
            }
            this.byteArray = new ByteArray();
            return;
        }// end function

        public function dispose() : void
        {
            if (this.byteArray)
            {
                this._byteArray.clear();
                this._byteArray = null;
            }
            return;
        }// end function

        public function set byteArray(param1:ByteArray) : void
        {
            this._byteArray = param1;
            this._byteArray.endian = Endian.LITTLE_ENDIAN;
            return;
        }// end function

        public function get byteArray() : ByteArray
        {
            return this._byteArray;
        }// end function

    }
}
